package org.example.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.example.constant.BusinessEnum;
import org.example.constant.HttpContains;
import org.example.model.Result;
import org.example.contant.ResourceContants;
import org.example.filter.TokenTranslationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfig extends WebSecurityConfigurerAdapter {

    //添加token解析过滤器
    @Autowired
    private TokenTranslationFilter tokenTranslationFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.cors().disable();
        http.csrf().disable();
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        //编写一个token解析过滤器，将token转换为security安全框架能够认证的用户信息，再存放到当前资源服务器的容器中
        http.addFilterBefore(tokenTranslationFilter, UsernamePasswordAuthenticationFilter.class);

        http.exceptionHandling()
                //处理无Token
                .authenticationEntryPoint(AuthenticationEntryPoint())
                //处理携带Token 但权限不足
                .accessDeniedHandler(AccessDeniedHandler());

        http.authorizeHttpRequests()
                .antMatchers(ResourceContants.RESOURCE_ALLOW_URLS).permitAll()
                //除了放行的请求，其他请求都需要身份验证
                .anyRequest().authenticated();

    }

    @Bean
    public AuthenticationEntryPoint AuthenticationEntryPoint() {
        return new AuthenticationEntryPoint(){
            @Override
            public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
                    throws IOException, ServletException {
                response.setCharacterEncoding(HttpContains.UTF_8);
                response.setContentType(HttpContains.APPLICATION_JSON);

                Result result = Result.fail(BusinessEnum.UN_AUTHORIZED);
                ObjectMapper objectMapper = new ObjectMapper();
                String s = objectMapper.writeValueAsString(result);
                PrintWriter writer = response.getWriter();
                writer.write(s);
                writer.flush();
                writer.close();

            }
        };
    }

    @Bean
    public AccessDeniedHandler AccessDeniedHandler() {
        return new AccessDeniedHandler(){
            @Override
            public void handle(HttpServletRequest request, HttpServletResponse response,
                               AccessDeniedException accessDeniedException) throws IOException, ServletException {
                response.setCharacterEncoding(HttpContains.UTF_8);
                response.setContentType(HttpContains.APPLICATION_JSON);

                Result result = Result.fail(BusinessEnum.ACCESS_DENY_FAIL);
                ObjectMapper objectMapper = new ObjectMapper();
                String s = objectMapper.writeValueAsString(result);
                PrintWriter writer = response.getWriter();
                writer.write(s);
                writer.flush();
                writer.close();
            }
        };
    }

}
